from utils import common
from lib.sensors.ssd1306.render import renderer
from lib.config.index import sensor_config
import time

class FontRenderer(renderer.Renderer):
    def __init__(self, oled):
        super().__init__(oled)
        self.__fonts = dict() #字库
        self.__current_line = 0
        self.__last_text = ''

    def set_font(self, font, font_size):
        """
        设置不同大小字库 8,12,16,24,32
        """
        self.__fonts[font_size] = font

    def display(self, string, x_axis, y_axis, font_size):
        """
        非字库
        显示ascii
        """
        if font_size == 8:
            self._display_font8(string, x_axis, y_axis)

        """
        字库
        显示支持中文字符串
        """
        if font_size not in self.__fonts:
            return
        if font_size == 12:
            self._display_font12(string, x_axis, y_axis)
        if font_size == 16:
            self._display_font16(string, x_axis, y_axis)
        if font_size == 24:
            self._display_font24(string, x_axis, y_axis)
        if font_size == 32:
            self._display_font32(string, x_axis, y_axis)

    def _display_font8(self, string, x_axis, y_axis):
        self.__oled.text(string, x_axis, y_axis)

    def _display_font12(self, string, x, y):
        offset = 0
        # print(string)
        for k in string:
            try:
                # print(k, _fonts[12])
                if k == " " or ord(k) == 119:
                    x += 12
                    continue
                data_code = k.encode("utf-8")
                if common.is_ascii(k):
                    idx = ord(k)
                    # print(idx)
                    byte_data = self.__fonts[12][str(idx)]
                else:
                    code = 0x00
                    # print(data_code)
                    code |= data_code[0] << 16  # 第一个字节
                    code |= data_code[1] << 8  # 第二个字节
                    code |= data_code[2]  # 第三个字节
                    # 将三个字节拼成Key得到一个24位的数字
                    # print(type(code), code)
                    byte_data = self.__fonts[12][str(code)]
                # print(byte_data)

                index = 0
                for y_offset in range(0, 12):  # y_offset  0-16
                    a = bin(byte_data[index + y_offset]).replace("0b", "")
                    b = bin(byte_data[index + y_offset + 1]).replace("0b", "")
                    # print(a,b,index + y_offset,index + y_offset+1)
                    index += 1

                    left8 = "{:0>8}".format(a)
                    right8 = "{:0>8}".format(b)
                    # print(left8, right8)
                    left = left8[2:8]
                    right = right8[4:8] + left8[0:2]
                    # print(left,right)

                    # print("----")
                    for x_offset in range(0, 6):  # x_offset 0-8
                        pos = 5 - x_offset
                        try:
                            self.__oled.pixel(
                                x + x_offset + offset, y + y_offset, int(left[pos])
                            )  # 画前6列
                            # print(x + x_offset, y + y_offset, left[x_ofe)fset])
                            self.__oled.pixel(
                                x + x_offset + offset + 6, y + y_offset, int(right[pos])
                            )  # 画后6列
                            # print(x + x_offset + 8, y + y_offset, right[x_offset])
                        except Exception as e:
                            print(e)
                offset += 12
            except Exception as e:
                print("error:")
                print(k, end="")

    def _display_font16(self, string, x, y):
        offset = 0
        # print(string)
        for k in string:
            if k == " ":
                x += 16
                continue
            data_code = k.encode("utf-8")
            if common.is_ascii(k):
                idx = ord(k)
                byte_data = self.__fonts[16][idx]
            else:
                code = 0x00
                # print(data_code)
                code |= data_code[0] << 16  # 第一个字节
                code |= data_code[1] << 8  # 第二个字节
                code |= data_code[2]  # 第三个字节
                # 将三个字节拼成Key得到一个24位的数字
                # print(type(code), code)
                byte_data = self.__fonts[16][code]
                # print(byte_data)

            index = 0
            for y_offset in range(0, 16):  # y_offset  0-16
                a = bin(byte_data[index + y_offset]).replace("0b", "")
                b = bin(byte_data[index + y_offset + 1]).replace("0b", "")
                # print(a,b,index + y_offset,index + y_offset+1)
                index += 1

                left = "{:0>8}".format(a)
                right = "{:0>8}".format(b)
                # print(left,right)

                for x_offset in range(0, 8):  # x_offset 0-8
                    pos = 7 - x_offset
                    self.__oled.pixel(
                        x + x_offset + offset, y + y_offset, int(left[pos])
                    )  # 画前8列
                    # print(x + x_offset, y + y_offset, left[x_offset])
                    self.__oled.pixel(
                        x + x_offset + offset + 8, y + y_offset, int(right[pos])
                    )  # 画后8列
                    # print(x + x_offset + 8, y + y_offset, right[x_offset])
            offset += 16

    def _display_font24(self, string, x_axis, y_axis):
        offset = 0
        for k in string:
            code = 0x00
            data_code = k.encode("utf-8")
            code |= data_code[0] << 16
            code |= data_code[1] << 8
            code |= data_code[2]
            byte_data = self.__fonts[24][code]
            for y in range(0, 24):
                a = bin(byte_data[y]).replace("0b", "")
                while len(a) < 8:
                    a = "0" + a

                b = bin(byte_data[y + 24]).replace("0b", "")
                while len(b) < 8:
                    b = "0" + b

                c = bin(byte_data[y + 48]).replace("0b", "")
                while len(c) < 8:
                    c = "0" + c
                for x in range(0, 8):
                    self.__oled.pixel(x_axis + offset + x, y + y_axis, int(a[x]))
                    self.__oled.pixel(x_axis + offset + x + 8, y + y_axis, int(b[x]))
                    self.__oled.pixel(x_axis + offset + x + 16, y + y_axis, int(c[x]))
            offset += 24

    def _display_font32(self, string, x_axis, y_axis):
        offset = 0
        for k in string:
            code = 0x00
            data_code = k.encode("utf-8")
            code |= data_code[0] << 16
            code |= data_code[1] << 8
            code |= data_code[2]
            byte_data = self.__fonts[32][code]
            for y in range(0, 32):
                a = bin(byte_data[y]).replace("0b", "")
                while len(a) < 8:
                    a = "0" + a

                b = bin(byte_data[y + 32]).replace("0b", "")
                while len(b) < 8:
                    b = "0" + b

                c = bin(byte_data[y + 64]).replace("0b", "")
                while len(c) < 8:
                    c = "0" + c

                d = bin(byte_data[y + 96]).replace("0b", "")
                while len(d) < 8:
                    d = "0" + d
                for x in range(0, 8):
                    self.__oled.pixel(x_axis + offset + x, y + y_axis, int(a[x]))
                    self.__oled.pixel(x_axis + offset + x + 8, y + y_axis, int(b[x]))
                    self.__oled.pixel(x_axis + offset + x + 16, y + y_axis, int(c[x]))
                    self.__oled.pixel(x_axis + offset + x + 24, y + y_axis, int(d[x]))
            offset += 32

    def text_cn(self, string, x_axis, y_axis, font_size):
        """显示包含中文的字符串"""
        self.display(string, x_axis, y_axis, font_size)

    def auto_text(self, text, x, y, font_size=12):
        """自动显示"""
        # print(text,x,y)
        self.text_cn(text, x, y, font_size)
        self.__oled.show()

    def pretty_line(self, string, font_size, max_char_line, delay):
        """格式化"""
        global current_line

        if sensor_config.is_debug():
            print(f"ssd1306 pretty line: {string},{font_size},{max_char_line},{delay}")

        # print(string)
        lines = [
            string[i: i + max_char_line] for i in range(0, len(string), max_char_line)
        ]
        x = 0
        for line in lines:
            # print(current_line, max_line)
            self.auto_text(line, x, current_line, font_size)
            current_line += font_size
            self.__oled.show()
            time.sleep(delay)

    def reset_line(self):
        self.__oled.clear()
        self.__current_line = 0

    def debug_show_text(self, text):
        """debug show last text
        """
        if not sensor_config.is_debug():
            return

        if self.__last_text != text:
            self.__last_text = text
            print("ssd1306 debug: ", text)

    def show_text(self, text, font_size=12, delay=0):
        """show text with json fonts
        需要提前加载字符点阵
        font_size： 8，12，,14，,16，,32
        """
        self.debug_show_text(text)
        x = 0
        max_line = self.__oled.height  # 当前OLED一屏能够显示的行点数，
        max_char_line = self.__oled.width // font_size  # 一行最多显示的字符数
        # print(text, max_char_line)
        lines = text.split("\n")
        for line in lines:
            if line == "":  # split的空白行
                continue
            if self.__current_line > max_line - 4:  # 最小需要5px，最后4px换到新页
                self.__oled.clear()
                self.__current_line = 0
            # 单行文本长度不超出
            if len(line) <= max_char_line:
                self.auto_text(line, x, self.__current_line, font_size)
                self.__oled.show()
                self.__current_line += font_size
                time.sleep(delay)
                continue
            # 超出自动处理换行
            self.pretty_line(line, font_size, max_char_line, delay)








